"""
设备资产管理缓存
"""

import logging
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta

logger = logging.getLogger(__name__)

class AssetCache:
    """设备资产缓存管理类"""
    
    def __init__(self):
        self._cache = {}
        self._cache_timestamps = {}
        self._cache_ttl = 300  # 缓存有效期5分钟
    
    def _is_cache_expired(self, key: str) -> bool:
        """检查缓存是否过期"""
        if key not in self._cache_timestamps:
            return True
        
        cache_time = self._cache_timestamps[key]
        return datetime.now() - cache_time > timedelta(seconds=self._cache_ttl)
    
    def _set_cache(self, key: str, data: Any) -> None:
        """设置缓存"""
        self._cache[key] = data
        self._cache_timestamps[key] = datetime.now()
    
    def _get_cache(self, key: str) -> Optional[Any]:
        """获取缓存"""
        if self._is_cache_expired(key):
            self._cache.pop(key, None)
            self._cache_timestamps.pop(key, None)
            return None
        return self._cache.get(key)
    
    def clear_cache(self, pattern: Optional[str] = None) -> None:
        """
        清除缓存
        
        Args:
            pattern: 缓存键模式，如果为None则清除所有缓存
        """
        if pattern is None:
            self._cache.clear()
            self._cache_timestamps.clear()
            logger.info("已清除所有设备资产缓存")
        else:
            keys_to_remove = [key for key in self._cache.keys() if pattern in key]
            for key in keys_to_remove:
                self._cache.pop(key, None)
                self._cache_timestamps.pop(key, None)
            logger.info(f"已清除匹配模式 '{pattern}' 的缓存，共 {len(keys_to_remove)} 项")
    
    def get_assets_by_type(self, asset_type: str, fetch_func: callable) -> List[Dict[str, Any]]:
        """
        根据类型获取设备资产（带缓存）
        
        Args:
            asset_type: 资产类型
            fetch_func: 数据获取函数
            
        Returns:
            设备资产列表
        """
        cache_key = f"assets_by_type:{asset_type}"
        
        # 尝试从缓存获取
        cached_data = self._get_cache(cache_key)
        if cached_data is not None:
            logger.debug(f"从缓存获取类型为 {asset_type} 的设备资产")
            return cached_data
        
        # 从数据库获取并缓存
        try:
            assets = fetch_func()  # 不传递参数，因为fetch_func已经是闭包，包含了asset_type
            self._set_cache(cache_key, assets)
            logger.debug(f"已缓存类型为 {asset_type} 的设备资产，共 {len(assets)} 项")
            return assets
        except Exception as e:
            logger.error(f"获取类型为 {asset_type} 的设备资产失败: {e}")
            return []
    
    def get_assets_by_department(self, department: str, fetch_func: callable) -> List[Dict[str, Any]]:
        """
        根据部门获取设备资产（带缓存）
        
        Args:
            department: 部门名称
            fetch_func: 数据获取函数
            
        Returns:
            设备资产列表
        """
        cache_key = f"assets_by_department:{department}"
        
        # 尝试从缓存获取
        cached_data = self._get_cache(cache_key)
        if cached_data is not None:
            logger.debug(f"从缓存获取部门为 {department} 的设备资产")
            return cached_data
        
        # 从数据库获取并缓存
        try:
            assets = fetch_func()  # 不传递参数，因为fetch_func已经是闭包，包含了department
            self._set_cache(cache_key, assets)
            logger.debug(f"已缓存部门为 {department} 的设备资产，共 {len(assets)} 项")
            return assets
        except Exception as e:
            logger.error(f"获取部门为 {department} 的设备资产失败: {e}")
            return []
    
    def get_asset_statistics(self, fetch_func: callable) -> Dict[str, Any]:
        """
        获取设备资产统计信息（带缓存）
        
        Args:
            fetch_func: 数据获取函数
            
        Returns:
            统计信息字典
        """
        cache_key = "asset_statistics"
        
        # 尝试从缓存获取
        cached_data = self._get_cache(cache_key)
        if cached_data is not None:
            logger.debug("从缓存获取设备资产统计信息")
            return cached_data
        
        # 从数据库获取并缓存
        try:
            stats = fetch_func()
            self._set_cache(cache_key, stats)
            logger.debug("已缓存设备资产统计信息")
            return stats
        except Exception as e:
            logger.error(f"获取设备资产统计信息失败: {e}")
            return {}
    
    def get_asset_by_id(self, asset_id: str, fetch_func: callable) -> Optional[Dict[str, Any]]:
        """
        根据ID获取设备资产（带缓存）
        
        Args:
            asset_id: 设备资产ID
            fetch_func: 数据获取函数
            
        Returns:
            设备资产信息
        """
        cache_key = f"asset_by_id:{asset_id}"
        
        # 尝试从缓存获取
        cached_data = self._get_cache(cache_key)
        if cached_data is not None:
            logger.debug(f"从缓存获取设备资产 {asset_id}")
            return cached_data
        
        # 从数据库获取并缓存
        try:
            asset = fetch_func()  # 不传递参数，因为fetch_func已经是闭包，包含了asset_id
            if asset:
                self._set_cache(cache_key, asset)
                logger.debug(f"已缓存设备资产 {asset_id}")
            return asset
        except Exception as e:
            logger.error(f"获取设备资产 {asset_id} 失败: {e}")
            return None
    
    def invalidate_asset(self, asset_id: str) -> None:
        """
        使指定设备资产的缓存失效
        
        Args:
            asset_id: 设备资产ID
        """
        cache_key = f"asset_by_id:{asset_id}"
        self._cache.pop(cache_key, None)
        self._cache_timestamps.pop(cache_key, None)
        
        # 清除相关的统计缓存
        self.clear_cache("asset_statistics")
        logger.debug(f"已使设备资产 {asset_id} 的缓存失效")
    
    def get_cache_info(self) -> Dict[str, Any]:
        """
        获取缓存信息
        
        Returns:
            缓存信息字典
        """
        total_items = len(self._cache)
        expired_items = sum(1 for key in self._cache.keys() if self._is_cache_expired(key))
        
        return {
            'total_items': total_items,
            'active_items': total_items - expired_items,
            'expired_items': expired_items,
            'cache_ttl_seconds': self._cache_ttl,
            'cache_keys': list(self._cache.keys())
        }